package cn.itsource.org.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;

import cn.hutool.crypto.digest.MD5;
import cn.itsource.basic.other.config.exception.BusinessException;
import cn.itsource.basic.service.BaseServiceImpl;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.RedisService;
import cn.itsource.org.domain.Employee;
import cn.itsource.org.domain.LoginInfo;
import cn.itsource.org.domain.User;
import cn.itsource.org.mapper.UserMapper;
import cn.itsource.org.query.UserQuery;
import cn.itsource.org.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

@Service
@Slf4j //日志注解
//Propagation.SUPPORTS:支持别人事务
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class UserServiceImpl extends BaseServiceImpl<User, UserQuery> implements IUserService {
    //基础查询由继承得到

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserMapper userMapper;


    @Override
    public AjaxResult checkPhone(String phone) {
        //1.验证手机号合法性
        boolean mobile = Validator.isMobile(phone);
        if (!mobile){
            throw new BusinessException("手机号有误,请重新输入...");
        }

        //2.校验手机号是否被注册过 select * from t_user where phone = #{phone}
        User user = userMapper.findByPhone(phone);

        if (user != null){
            throw new BusinessException("用户已经注册过了...");
        }

        return AjaxResult.createSuccess("手机号验证通过");

    }


    /**
     * 发送验证码
     * @param phone
     * @return
     */
    @Override
    public AjaxResult sendMobileCode(String phone, HttpServletRequest request) {
        //验证手机号
        boolean mobile = Validator.isMobile(phone);
        if (!mobile){
            throw new BusinessException("手机号有误,请重新输入...");
        }

        //2.校验手机号是否被注册过
        User user = userMapper.findByPhone(phone);

        if (user != null){
            throw new BusinessException("用户已经注册过了...");
        }

        //3.拦截同一个ip一直获取验证码   拼出来的是ip地址+接口地址     接口防刷
       /* String ipPhoneStr = request.getRemoteAddr() + request.getRequestURI();
        //把（ip地址+接口地址 127.0.0.1xxxx）作为key去获取
        //第一次获取res是null，
        ////一分钟之内再来获取就有值了 res 有值
        String res = redisService.getKeyObjectValue(ipPhoneStr, String.class);
        if (res != null){
            throw new BusinessException("兄die,你不正常...");
        }
        //存ip到redis中,保持1分钟,1分钟内重复获取抛出上面的异常
        //把（ip地址+接口地址 127.0.0.1xxxx）作为key value:手机号  存1分钟
        //一分钟之内再来获取就有值了
        redisService.setStringKeyAndValue(10,ipPhoneStr,phone);*/

        //4.生成验证码,保存到redis 5分钟
        String code = RandomUtil.randomNumbers(4);
        //phone:手机号  code:验证码
        redisService.setStringKeyAndValue(phone,code,5);
        //[宠物乐园验证码]:7501
        log.info("[宠物乐园验证码]:{}",code);

        //调用发送验证码的服务 打印知道存到redis里面的验证码就行了,不发送
        //SendMobileMessageUtil.sendMobileMessage(phone,code);
        return AjaxResult.createSuccess("发送验证码成功");
    }

    @Override
    public AjaxResult registerUser(User user) {
        //验证手机号
        boolean mobile = Validator.isMobile(user.getPhone());
        if (!mobile){
            throw new BusinessException("手机号有误,请重新输入...");
        }

        //2.校验手机号是否被注册过
        User dbUser = userMapper.findByPhone(user.getPhone());

        if (dbUser != null){
            throw new BusinessException("用户已经注册过了...");
        }


        //获取Redis的验证码,如果不存在,已失效
        String code = redisService.getKeyObjectValue(user.getPhone(), String.class);
        /**
         * if (StringUtils.isBlank(code)){
         *             throw new BusinessException("验证码已经失效,请重新获取");
         *         }
         */
        Optional.ofNullable(code).orElseThrow(() -> new BusinessException("验证码已经失效,请重新获取"));

        //比对验证码
        if (!StringUtils.equals(user.getCode(),code)){
            throw new BusinessException("验证码错误...");
        }

        //通过钩子设置盐和密码
        user.init();

        //注册账号入库
        userMapper.insertSelective(user);

        return AjaxResult.createSuccess();
    }

    @Override
    public AjaxResult login(User user) {

        //1.根据用户名查询用户信息   //账户名与密码不匹配，请重新输入
        User dbUser = userMapper.selectByUsername(user);
        //1.1.如果查不到，直接抛异常
        Optional.ofNullable(dbUser).orElseThrow(()->new BusinessException("账户名与密码不匹配，请重新输入1"));

        //2.比对密码（大坑） 对传进来密码加盐加密  和 数据库的密码串进行比对
        //对传进来密码加盐加密  盐:从数据库查询的对象中来
        String pagePwd = MD5.create().setSalt(dbUser.getSalt().getBytes()).digestHex(user.getPassword());

        //2.1比对不通过，抛异常
        if (!StringUtils.equals(pagePwd,dbUser.getPassword())){
            throw new BusinessException("账户名与密码不匹配，请重新输入2");
        }

        //3.成功的登录信息放到redis  key：token字符串  value：登录信息
        String token = IdUtil.fastSimpleUUID();//令牌
        //3.1封装通用的登录对象
        LoginInfo loginInfo = BeanUtil.copyProperties(dbUser, LoginInfo.class);
        //todo 插眼
        loginInfo.setUserId(dbUser.getId());
        loginInfo.setToken(token);
        //3.2存redis 30分钟
        redisService.setStringKeyAndValue(token,loginInfo,30);

        //4.返回信息
        return AjaxResult.createSuccess(loginInfo);

    }


}
